package com.jack006.article.controller;

import com.jack006.api.BaseController;
import com.jack006.api.config.RabbitMQConfig;
import com.jack006.api.controller.article.ArticleControllerApi;
import com.jack006.api.controller.article.ArticleHtmlControllerApi;
import com.jack006.api.controller.article.ArticlePortalControllerApi;
import com.jack006.article.service.ArticleService;
import com.jack006.enums.ArticleCoverType;
import com.jack006.enums.ArticleReviewStatus;
import com.jack006.enums.YesOrNo;
import com.jack006.exception.GraceException;
import com.jack006.grace.result.GraceJSONResult;
import com.jack006.grace.result.ResponseStatusEnum;
import com.jack006.pojo.Category;
import com.jack006.pojo.bo.NewArticleBO;
import com.jack006.pojo.vo.ArticleDetailVO;
import com.jack006.utils.JsonUtils;
import com.jack006.utils.PagedGridResult;
import com.mongodb.client.gridfs.GridFSBucket;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Classname ArticleController
 * @Description 文章业务实现
 * @Date 2021-06-10 08:15
 * @Created by jack
 */
@RestController
public class ArticleController extends BaseController implements ArticleControllerApi {

    final static Logger logger = LoggerFactory.getLogger(ArticleController.class);

    @Autowired
    private ArticleService articleService;
    @Autowired
    private GridFSBucket gridFSBucket;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ArticlePortalControllerApi articlePortalControllerApi;
    @Autowired
    private ArticleHtmlControllerApi articleHtmlControllerApi;

    @Value("${freemarker.html.article}")
    private String articlePath;


    @Override
    public GraceJSONResult createArticle(@Valid NewArticleBO newArticleBO) {

        // 判断文章封面类型，单图必填，纯文字则设置为空
        if (newArticleBO.getArticleType() == ArticleCoverType.ONE_IMAGE.type) {
            if (StringUtils.isBlank(newArticleBO.getArticleCover())) {
                return GraceJSONResult.errorCustom(ResponseStatusEnum.ARTICLE_COVER_NOT_EXIST_ERROR);
            }
        } else {
            newArticleBO.setArticleCover("");
        }
        // 判断分类 ID 是否存在 并返回目录
        Category category = getCategory(newArticleBO.getCategoryId());
        articleService.createCategory(newArticleBO,category);

        return GraceJSONResult.ok();
    }


    private void doDownloadArticleHtmlByMQ(String articleId,String articleMongoId) {
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.EXCHANGE_ARTICLE,
                "article.download.do",
                articleId+","+articleMongoId
        );
    }

    private void doDownloadArticleHtml(String articleId,String articleMongoId) {

//        String serviceId = "SERVICE-ARTICLE-HTML";
//        String url =
//                "http://"+serviceId+"/article/html/download?" +
//                        "articleId="+articleId
//                        +"&articleMongoId="+articleMongoId;
//        ResponseEntity<Integer> responseEntity = restTemplate.getForEntity(url, Integer.class);
//        Integer status = responseEntity.getBody();
        Integer status = null;
        try {
            status = articleHtmlControllerApi.download(articleId,articleMongoId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (status != HttpStatus.OK.value()) {
            GraceException.display(ResponseStatusEnum.ARTICLE_REVIEW_ERROR);
        }
    }

    @Override
    public GraceJSONResult queryMyList(String userId, String keyword,
                                       Integer status, Date startDate, Date endDate,
                                       Integer page, Integer pageSize) {
        if (StringUtils.isBlank(userId)) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ARTICLE_QUERY_PARAMS_ERROR);
        }
        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        // 查询文章列表
        PagedGridResult result = articleService.queryArticleList(userId,keyword,
                status,startDate,endDate,page,pageSize);

        return GraceJSONResult.ok(result);
    }

    @Override
    public GraceJSONResult queryAllList(Integer status, Integer page, Integer pageSize) {

        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult gridResult = articleService.queryArticleListAdmin(status,page,pageSize);

        return GraceJSONResult.ok(gridResult);
    }

    @Override
    public GraceJSONResult doReview(String articleId, Integer passOrNot) {

        Integer pendingStatus;
        if (passOrNot == YesOrNo.YES.type) {
            // 审核通过
            pendingStatus = ArticleReviewStatus.SUCCESS.type;
        } else if (passOrNot == YesOrNo.NO.type) {
            // 审核失败
            pendingStatus = ArticleReviewStatus.FAILED.type;
        } else {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.ARTICLE_REVIEW_ERROR);
        }

        // 修改文章状态
        articleService.updateArticleReviewStatus(articleId,pendingStatus);

        if (pendingStatus == ArticleReviewStatus.SUCCESS.type) {
            // 审核成功， 生成文章详情页静态 html
            try {
                // createArticleHtml(articleId);
                String articleHtmlGridId = createArticleHtmlToGridFS(articleId);
                // 存储到对应的文章，进行关联保存
                articleService.updateArticleToGridFs(articleId,articleHtmlGridId);
                // 调用消费端下载文章
                // doDownloadArticleHtml(articleId,articleHtmlGridId);
                // 发送消息到 MQ 队列，调用消费者，执行下载 html
                doDownloadArticleHtmlByMQ(articleId,articleHtmlGridId);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return GraceJSONResult.ok();
    }

    public String createArticleHtmlToGridFS(String articleId) throws Exception {

        // 0.配置 freemarker 基本环境
        Configuration cfg = new Configuration(Configuration.getVersion());
        // 声明 freemarker 模板所需要加载的目录的位置
        String classPath = this.getClass().getResource("/").getPath();
        cfg.setDirectoryForTemplateLoading(new File(classPath+"templates"));

        // 1. 获得现有的模板 ftl 文件
        Template template = cfg.getTemplate("detail.ftl","utf-8");

        // 2. 获得文章详情数据
        ArticleDetailVO articleDetail = getArticleDetail(articleId);

        Map<String,Object> map = new HashMap<>();
        map.put("articleDetail",articleDetail);

        String htmlContent = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);

        InputStream inputStream = IOUtils.toInputStream(htmlContent);
        ObjectId htmlFileId = gridFSBucket.uploadFromStream(articleDetail.getId() + ".html", inputStream);

        return htmlFileId.toString();

    }

    @GetMapping("createHtml")
    @ResponseBody
    public void createArticleHtml(String articleId) throws Exception {

        // 0.配置 freemarker 基本环境
        Configuration cfg = new Configuration(Configuration.getVersion());
        // 声明 freemarker 模板所需要加载的目录的位置
        String classPath = this.getClass().getResource("/").getPath();
        cfg.setDirectoryForTemplateLoading(new File(classPath+"templates"));

        // 1. 获得现有的模板 ftl 文件
        Template template = cfg.getTemplate("detail.ftl","utf-8");

        // 2. 获得文章详情数据
        ArticleDetailVO articleDetail = getArticleDetail(articleId);

        // 3.融合动态数据 ftl, 生成 html
        File tempDic = new File(articlePath);
        if (!tempDic.exists()) {
            tempDic.mkdirs();
        }

        Map<String,Object> map = new HashMap<>();
        map.put("articleDetail",articleDetail);


        articlePath = articlePath +File.separator+articleDetail.getId()+".html";
        Writer out = new FileWriter(articlePath);
        template.process(map,out);
        out.close();
    }



    // 发起远程调用 rest,获得文章详情数据
    public ArticleDetailVO getArticleDetail(String articleId) {

//        String serviceId = "SERVICE-ARTICLE";
//        String userServerUrlExecute = "http://"+serviceId+"/portal/article/detail?articleId="+ articleId;
//        ResponseEntity<GraceJSONResult> responseEntity = restTemplate.getForEntity(userServerUrlExecute, GraceJSONResult.class);
//        GraceJSONResult bodyResult = responseEntity.getBody();

        GraceJSONResult bodyResult = articlePortalControllerApi.detail(articleId);
        ArticleDetailVO detailVO = null;
        if (bodyResult.getStatus() == 200) {
            String detailJson = JsonUtils.objectToJson(bodyResult.getData());
            detailVO = JsonUtils.jsonToPojo(detailJson, ArticleDetailVO.class);
        }
        return detailVO;
    }

    @Override
    public GraceJSONResult delete(String userId, String articleId) {
        articleService.deleteArticle(userId,articleId);
        return GraceJSONResult.ok();
    }

    @Override
    public GraceJSONResult withdraw(String userId, String articleId) {
        articleService.withdrawArticle(userId,articleId);
        return GraceJSONResult.ok();
    }
}
